home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume15 / bootmenu / part01 next >
Encoding:
Text File  |  1990-12-16  |  46.9 KB  |  1,714 lines

  1. Newsgroups: comp.sources.misc
  2. X-UNIX-From: gwr@linus.mitre.org
  3. keywords: fdisk partition boot menu bootmenu pfdisk
  4. organization: The MITRE Corporation, Bedford, MA.
  5. summary: primary boot sector program with menu
  6. subject: v15i084: BOOTMENU and PFDISK 1.3 (part 1/2)
  7. from: gwr@linus.mitre.org
  8. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  9.  
  10. Posting-number: Volume 15, Issue 84
  11. Submitted-by: gwr@linus.mitre.org
  12. Archive-name: bootmenu/part01
  13.  
  14. Here is part 1 of the BOOTMENU and PFDISK 1.3 distribution.
  15.  
  16. BOOTMENU is a replacement primary boot sector for MS-DOS compatible
  17. machines which allows boot-time selection of the active hard disk
  18. partition using a menu.  For example, users with both UNIX and DOS
  19. on their hard disk can choose which system to use at boot time.
  20.  
  21. PFDISK is a replacement "fdisk" command for
  22. installing BOOTMENU without clobbering your partition table.
  23.  
  24. See the README file at the beginning of the shell archive below for a
  25. general description of this package.  Program documentation for both
  26. BOOTMENU and PFDISK are at the beginning of the second posting.
  27.  
  28. Gordon W. Ross  (M/S E095)    internet: gwr@linus.mitre.org
  29. The MITRE Corporation        uucp: {decvax|philabs}!linus!gwr
  30. Burlington Road              office phone: 617-271-3205
  31. Bedford, MA 01730 (U.S.A.)
  32.  
  33. #! /bin/sh
  34. # This is a shell archive, meaning:
  35. # 1. Remove everything above the #! /bin/sh line.
  36. # 2. Save the resulting text in a file.
  37. # 3. Execute the file with /bin/sh (not csh) to create the files:
  38. #    README
  39. #    pfdisk.man
  40. #    Changes
  41. #    Makefile
  42. #    pfdisk.c
  43. #    syscodes.c
  44. #    syscodes.h
  45. #    sysdep.h
  46. #    s_esix.c
  47. #    s_i386.c
  48. #    s_unix.c
  49. #    s_msdos.c
  50. # This archive created: Tue Oct 23 13:53:17 1990
  51. # By:    Gordon W. Ross (The MITRE Corporation, Bedford, MA.)
  52. export PATH; PATH=/bin:$PATH
  53. echo shar: extracting "'README'" '(3148 characters)'
  54. if test -f 'README'
  55. then
  56.     echo shar: will not over-write existing file "'README'"
  57. else
  58. cat << \SHAR_EOF > 'README'
  59.  
  60. BOOTMENU is a replacement primary boot sector for MS-DOS compatible
  61. machines which allows boot-time selection of the active hard disk
  62. partition using a menu.  For example, users with both UNIX and DOS
  63. on their hard disk can choose which system to use at boot time.
  64.  
  65. BOOTAUTO is similar to BOOTMENU but allows both unattended reboot
  66. and the ability to override the automatic selection of the active
  67. partition at boot-time.  (I used to call this version boot-hdp).
  68.  
  69. BOOTMENU cannot do an unattended reboot but is very small and
  70. (as a result) will not be clobbered if you use the SpeedStor
  71. disk formatting/diagnostics program.  (Notes about SpeedStor's
  72. usage of the primary boot sector are in the file SStor.txt).
  73.  
  74. PFDISK is a replacement for both DOS and UNIX fdisk programs.
  75. This replacement is distinguished for its ability to put
  76. an arbitrary binary image into the primary boot sector without
  77. clobbering an existing partition table.  PFDISK has no boot
  78. program built-in, but allows you to take the boot program
  79. from a file.  At least one of the boot program files, such as
  80. BOOTMENU, must be available to PFDISK if it is expected to
  81. initialize a newly formatted disk.  Unlike MSDOS fdisk,
  82. PFDISK correctly handles partition entries which extend
  83. beyond cyl 1023.  Unlike UNIX fdisk, PFDISK is not confused
  84. about the difference between highest-usable-cylinder-number
  85. and (beginning-cylinder plus number-of-cylinders).
  86.  
  87. Documentation included:
  88.  
  89. The file bootmenu.doc explains how to install and use the new
  90. boot programs.  The file pfdisk.man is manual entry in UNIX *roff
  91. format, and pfdisk.doc is a formatted copy for those without nroff.
  92.  
  93. How to compile:
  94.  
  95. To build pfdisk, either edit the Makefile to uncomment the
  96. appropriate line (i.e. SYS=i386) and type "make", or
  97. use a make command line like:
  98.     make SYS=i386
  99. This will just build the pfdisk program and boot sector binaries.
  100. It will not try to modify the hard disk boot sector.
  101.  
  102. The boot program binaries are distributed as simple HEX encoded
  103. text files.  The (included) program hex2bin will convert them
  104. for the benefit of those without the MASM (DOS) assembler.
  105.  
  106. Related packages (available separately):
  107.  
  108. The LOSS1024.FIX package contains patches for MSDOS 3.3 to allow use
  109. of the first 1024 cylinders of a hard disk when the disk controller
  110. BIOS has installed disk parameters showing more than 1024 cylinders.
  111. Note that this patch is designed for use on PC/AT compatible disk
  112. controllers that have a BIOS parameter override feature, such as the
  113. RLL and ESDI controllers by Adaptec and Western Digital.
  114.  
  115. The ESIX-BOOT package contains patches to make ESIX (Everex Systems
  116. SysV/386) boot from an inactive partition.  Normally, ESIX will refuse
  117. to boot unless its partition is marked as active.  These patches allow
  118. one to configure the partition table such that bootmenu will always
  119. present its boot menu (no partition marked active).
  120.  
  121. Send e-mail if you are interested in either of the above.
  122.  
  123. Gordon W. Ross  (M/S E095)    internet: gwr@linus.mitre.org
  124. The MITRE Corporation        uucp: {decvax|philabs}!linus!gwr
  125. Burlington Road              office phone: 617-271-3205
  126. Bedford, MA 01730 (U.S.A.)
  127.  
  128. SHAR_EOF
  129. if test 3148 -ne "`wc -c < 'README'`"
  130. then
  131.     echo shar: error transmitting "'README'" '(should have been 3148 characters)'
  132. fi
  133. fi # end of overwriting check
  134. echo shar: extracting "'pfdisk.man'" '(6386 characters)'
  135. if test -f 'pfdisk.man'
  136. then
  137.     echo shar: will not over-write existing file "'pfdisk.man'"
  138. else
  139. cat << \SHAR_EOF > 'pfdisk.man'
  140. .TH PFDISK 8 "Oct 1990" "Release 1.3"
  141. .SH NAME
  142. pfdisk \- partition fixed disk
  143. .SH SYNOPSIS
  144. .B pfdisk
  145. .I device
  146. .SH DESCRIPTION
  147. .LP
  148. .B pfdisk
  149. partitions the fixed disk identified as
  150. .I device
  151. into (at most) four parts, each of which may
  152. be independently loaded with an operating system.
  153. The actual name of
  154. .I device
  155. depends on the operating system in use.
  156. For ESIX (System V/386) the device name is either
  157. "/dev/rdsk/0s0" or "/dev/rdsk/1s0".
  158. For Minix, it is "/dev/hd0" or "/dev/hd5".
  159. For MS-DOS it is a single digit (zero or one).
  160. .LP
  161. .B pfdisk
  162. reads the hard disk partition table from block zero of
  163. .I device
  164. into memory and allows the user to examine, modify, or save the
  165. partition table.  A regular file may be used instead of a real
  166. .I device
  167. for testing purposes, though the device geometry must be specified
  168. manually, and some systems will requrire a file-name argument with
  169. the "R" and "W" commands (DOS, ESIX).
  170. .LP
  171. The partition table on
  172. .I device
  173. is NOT modified unless the write command (W) is used with no argument.
  174. .SH USAGE
  175. .SS Commands
  176. .LP
  177. All
  178. .B pfdisk
  179. commands consist of a command word followed by optional
  180. blank-separated command arguments.
  181. Note that only the first letter of a command word is significant
  182. (except for "wq" and "q!").
  183. All command letters are accepted in either upper or lower case.
  184. Numeric arguments are specified using C syntax.
  185. Extra arguments are silently ignored.
  186. .LP
  187. The commands are:
  188. .TP
  189. .B ?
  190. Prints a command summary (help).
  191. .TP
  192. .BI 1 " sys_id first last sys_name"
  193. Set the partition table entry for part one, using:
  194. .I sys_id
  195. as its system ID code,
  196. .I first
  197. as the lowest numbered cylinder it uses,
  198. .I last
  199. as the highest numbered cylinder it uses, and
  200. .I sys_name
  201. (optional) as the system name (in the menu name table).
  202. .TP
  203. .BI 2|3|4 " sys-id first last sys-name"
  204. Similar to
  205. .B 1
  206. but sets partition two, three, or four, respectively.
  207. .TP
  208. .BI A " number"
  209. Mark partition
  210. .I number
  211. as active (so it will be used for booting).  If
  212. .I number
  213. is zero, no partition will be active.
  214. .TP
  215. .BI G " cylinders heads sectors"
  216. Inform
  217. .B pfdisk
  218. what the geometry of the device is.
  219. .TP
  220. .B I
  221. Print a summary of the known ID codes.
  222. .TP
  223. .B L
  224. List the partition table.
  225. See
  226. .B "Output Format"
  227. below.
  228. .TP
  229. .B Q
  230. Quit without saving.  If the memory copy of the partition table was
  231. modified, a warning will be issued and the command ignored.
  232. .TP
  233. .B Q!
  234. Quit, even if the memory copy of the partition table was not saved.
  235. .TP
  236. .BI R " file-name"
  237. Read boot sector from
  238. .I file-name
  239. (if given) otherwise read from
  240. .I device.
  241. .TP
  242. .BI W " file-name"
  243. Write boot sector to
  244. .I file-name.
  245. (if given) otherwise write to
  246. .I device.
  247. .TP
  248. .B WQ
  249. Same as "write" followed by "quit".
  250. .TP
  251. .B #
  252. This line is a comment (to be ignored).
  253. .SS "Output Format"
  254. .LP
  255. Here is a sample of the output from the
  256. .B L
  257. command:
  258. .LP
  259. .nf
  260. # Partition table on device: /dev/rdsk/0s0
  261. geometry 1222 15 34 (cyls heads sectors)
  262. #  ID  First(cyl)  Last(cyl)  Name     # start, length (sectors)
  263. 1   4      0        127       MS-LOSS  # 34, 65246
  264. 2 129    128        255       Minix    # 65280, 65280
  265. 3   0      0          0                # 0, 0
  266. 4  99    256       1220       ESIX     # 130560, 492150
  267. # note:  last(4): phys=(1023,14,34) logical=(1220,14,34)
  268. active: 4
  269. .fi
  270. .LP
  271. This output format is carefully constructed so that it
  272. may be saved in a file  (by redirecting standard output)
  273. and later used as input (by redirecting standard input).
  274. On a UNIX system, one can save this output using the command:
  275. .IP
  276. (echo L) | pfdisk device-name >
  277. .I save-file
  278. .LP The printable representation saved in
  279. .I save-file
  280. is a complete record of the partition table.
  281. On a UNIX system, one could use
  282. .I save-file
  283. to re-initialize the partition table using the command:
  284. .IP
  285. (cat save-file ; echo wq) | pfdisk device-name
  286. .LP
  287. Consistency of each partition table entry is checked
  288. while the table is listed.  Any inconsistencies discovered
  289. are reported in a commentary note as shown above.
  290. .SS "Physical vs. Logical"
  291. .LP
  292. Each partition table entry has both "physical" and a "logical" fields.
  293. The physical fields specify the lowest and highest cylinder,head,sector
  294. combinations to be used in that partition.  The logical start field
  295. has the total number of sectors which precede this partition, and
  296. the logical length field has the total number of sectors contained
  297. in this partition.  These fields should be self consistent unless
  298. the disk has more than 1024 cylinders.
  299. .LP
  300. The physical cylinder fields are only ten-bits wide so the contents
  301. are limited to 1023. The logical sector fields are 32 bits wide and
  302. always show the true logical beginning and length of the partition.
  303. Generally, the physical start field is used only to locate the
  304. secondary boot sector, and the logical start and length fields are
  305. used to actually delimit the partition used by a particular system.
  306. .SS "Partition Names"
  307. .LP
  308. The
  309. .B Name
  310. field in the partition table is treated specially if the
  311. .B bootmenu
  312. program is installed in the primary boot sector.
  313. (See the file bootmenu.doc for more information.)
  314. .B pfdisk
  315. can recognize the name table used by
  316. .B bootmenu
  317. and will show the actual names present in that name table.
  318. If any other boot program is used then the
  319. .B Name
  320. field reflects the result of a table-lookup of the system ID.
  321. .LP
  322. If you provide a name when setting any partition entry, the
  323. boot-sector is marked as using a name table, so that on
  324. subsequent uses of
  325. .B pfdisk
  326. you will see the partition names you have specified.
  327. .SS "Boot program replacement"
  328. .LP
  329. You can replace the boot program in your boot sector without
  330. affecting the partition table by using
  331. .B pfdisk
  332. as follows.  First, (as always) save a copy of the current boot
  333. sector (on a floppy) using the "W file" command.  Then, use the
  334. "R file" command to read the new boot program.
  335. If the boot program read in is less than 446 bytes long, the
  336. partition table will be unchanged.
  337. .LP
  338. Unlike the DOS or UNIX
  339. .B fdisk
  340. programs,
  341. .B pfdisk
  342. has
  343. .I NO
  344. boot program compiled into its executable image.
  345. If you wish to use
  346. .B pfdisk
  347. to partition a newly formatted hard disk, you must have a boot program
  348. image available to read in using the "r file" command.
  349. Two boot programs, "bootmenu.bin" and "bootauto.bin" are distributed with
  350. .B pfdisk
  351. and should be found with its source files.  See the file bootmenu.doc
  352. for further information about these boot programs.
  353. .SH AUTHOR
  354. Gordon W. Ross
  355. SHAR_EOF
  356. if test 6386 -ne "`wc -c < 'pfdisk.man'`"
  357. then
  358.     echo shar: error transmitting "'pfdisk.man'" '(should have been 6386 characters)'
  359. fi
  360. fi # end of overwriting check
  361. echo shar: extracting "'Changes'" '(1131 characters)'
  362. if test -f 'Changes'
  363. then
  364.     echo shar: will not over-write existing file "'Changes'"
  365. else
  366. cat << \SHAR_EOF > 'Changes'
  367. New in version 1.3:
  368. Oct 90
  369.     Updated documentation for comp.sources.misc posting.
  370.     Cleaned up slightly, using unsigned where appropriate.
  371.     Forced "small" model for MicroSoft C compiler. (DOS...)
  372.     pfdisk command letters can be upper or lower case
  373.     Added partition ID codes as (generously) reported by
  374.         leendert@cs.vu.nl (Leendert van Doorn)
  375.  
  376. New in version 1.2:
  377. Sept '90
  378.     Added new, smaller version of boot program (BOOTMENU).
  379.     Renamed boot-hdp to BOOTAUTO (more descriptive of its function?)
  380.     Added prompt (people were confused wihout it)
  381.     Made pfdisk show real name field with sysid==0.
  382.     Made pfdisk set the signature whenever a (1,2,3,4) command
  383.         specifies the optional name argument.
  384.     Made pfdisk complain about invalid boot sector and mark it valid.
  385.  
  386. New in version 1.1:
  387. Feb '90
  388.     Added MSDOS compatibility to hex2bin.c
  389.     Moved ESIX patches into a separate package.
  390.  
  391.     Renamed s_minix.c to s_unix.c (it's generic)
  392.     Created an s_isc.c for Interactive Systems UNIX
  393.  
  394.     Fixed inconsistencies in esix-fix.sh and
  395.     Removed byte-order dependencies from pfdisk.c
  396.  
  397.     Revised instructions in boot-hdp.doc
  398.  
  399. Version 1.0 released (initial beta)
  400. SHAR_EOF
  401. if test 1131 -ne "`wc -c < 'Changes'`"
  402. then
  403.     echo shar: error transmitting "'Changes'" '(should have been 1131 characters)'
  404. fi
  405. fi # end of overwriting check
  406. echo shar: extracting "'Makefile'" '(1629 characters)'
  407. if test -f 'Makefile'
  408. then
  409.     echo shar: will not over-write existing file "'Makefile'"
  410. else
  411. cat << \SHAR_EOF > 'Makefile'
  412. # This makefile supports all UNIX-like systems.
  413. # Uncomment one of the SYS definitions below, or
  414. # use a make command like:
  415. #    make SYS=esix
  416. # (For compiling on MS-DOS, see make_msc.bat)
  417. # (To compile on Minix, use:  make minix)
  418. #
  419. # Uncomment for ESIX  Sys.V/386 Rel. 3.2
  420. #SYS=esix
  421. # Uncomment for other Sys.V/386 systems (ISC,SCO,Intel...)
  422. #SYS=i386
  423. # Uncomment for MSDOS with UNIX-style make (i.e. ndmake)
  424. #SYS=msdos
  425. # Uncomment for other UNIX-like systems
  426. SYS=unix
  427.  
  428. # Compilation options:
  429. CC=cc
  430. CFLAGS=-g
  431.  
  432. FILES1=    README pfdisk.man Changes Makefile pfdisk.c syscodes.c \
  433.  syscodes.h sysdep.h s_esix.c s_i386.c s_unix.c s_msdos.c
  434. FILES2= bootmenu.doc pfdisk.doc SStor.txt bootmenu.asm bootauto.asm \
  435.  asm2bin.bat make_msc.bat bootmenu.hex bootauto.hex hex2bin.c
  436.  
  437. OBJS= pfdisk.o syscodes.o s_$(SYS).o
  438. LSRC= pfdisk.c syscodes.c s_$(SYS).c
  439.  
  440. test: pfdisk
  441.     (echo "g 1222 15 34";\
  442.      echo "1  4   0  127 MS-LOSS";\
  443.      echo "4 99 128 1221 ESIX";\
  444.      echo "a 4"; echo l; echo wq \
  445.     ) | pfdisk /dev/null
  446.  
  447. all: pfdisk bootmenu.bin bootauto.bin
  448.  
  449. pfdisk: $(OBJS)
  450.     $(CC) $(CFLAGS) -o $@ $(OBJS)
  451.  
  452. minix: bootmenu.bin bootauto.bin
  453.     $(CC) $(CFLAGS) -o pfdisk $(LSRC)
  454.  
  455. pfdisk.o : syscodes.h sysdep.h
  456. syscodes.o : syscodes.h
  457. s_$(SYS).o : sysdep.h
  458.  
  459. lint: $(LSRC)
  460.     lint $(CFLAGS) $(LSRC)
  461.  
  462. bootmenu.bin: hex2bin
  463.     hex2bin <bootmenu.hex >bootmenu.bin
  464. bootauto.bin: hex2bin
  465.     hex2bin <bootauto.hex >bootauto.bin
  466.  
  467. pfdisk.doc: pfdisk.man
  468.     nroff tmac.an pfdisk.man |col -bh >pfdisk.doc
  469.  
  470. clean:
  471.     rm -f *.o
  472.  
  473. Shar1.out: Head1.txt $(FILES1)
  474.     (cat Head1.txt ; shar -v -c $(FILES1)) > $@
  475. Shar2.out: Head2.txt $(FILES2)
  476.     (cat Head2.txt ; shar -v -c $(FILES2)) > $@
  477.  
  478. SHAR_EOF
  479. if test 1629 -ne "`wc -c < 'Makefile'`"
  480. then
  481.     echo shar: error transmitting "'Makefile'" '(should have been 1629 characters)'
  482. fi
  483. fi # end of overwriting check
  484. echo shar: extracting "'pfdisk.c'" '(15690 characters)'
  485. if test -f 'pfdisk.c'
  486. then
  487.     echo shar: will not over-write existing file "'pfdisk.c'"
  488. else
  489. cat << \SHAR_EOF > 'pfdisk.c'
  490. /*
  491.  * pfdisk - Partition a Fixed DISK
  492.  *    by Gordon W. Ross, Jan. 1990
  493.  *
  494.  * See the file "pfdisk.doc" for user instructions.
  495.  *
  496.  * This program uses a simple, line-oriented interpreter,
  497.  * designed for both interactive and non-interactive use.
  498.  * To facilitate non-interactive use, the output from the
  499.  * 'L' (list partitions) command is carefully arranged so it
  500.  * can be used directly as command input.  Neat trick, eh?
  501.  */
  502.  
  503. char *versionString =
  504.   "# pfdisk version 1.2 by Gordon W. Ross  Aug. 1990\n";
  505.  
  506. /* These don't really matter.  The user is asked to set them. */
  507. #define DEFAULT_CYLS 306
  508. #define DEFAULT_HEADS 4
  509. #define DEFAULT_SECTORS 17
  510. #define PROMPT_STRING "pfdisk> "
  511.  
  512. #include <stdio.h>
  513. #include <string.h>
  514. #include <ctype.h>
  515. #include "sysdep.h"
  516. #include "syscodes.h"
  517.  
  518. typedef unsigned char uchar;
  519. typedef unsigned int uint;
  520. typedef unsigned long ulong;
  521.  
  522. struct part {    /* An entry in the partition table */
  523.   uchar    active;        /* active flag (0x80 or 0) */
  524.   uchar    b_head;        /* begin head */
  525.   uchar    b_sec;        /*      sector */
  526.   uchar    b_cyl;        /*     cylinder */
  527.   uchar    sysid;        /* system id (see sysid.c) */
  528.   uchar    e_head;        /* end  head */
  529.   uchar    e_sec;        /* end    sector */
  530.   uchar    e_cyl;        /* end    cylinder */
  531.   /* These two are just longs, but this way is machine independent. */
  532.   uchar    lsBeg[4];    /* logical sectors, beginning */
  533.   uchar    lsLen[4];    /* logical sectors, length */
  534. };
  535.  
  536. #define LOC_PT        0x1BE
  537. #define LOC_NT        0x180
  538. #define LOC_GWR        0x1A0
  539. #define MAGIC_LOC    0x1FE
  540. #define MAGIC_0        0x55
  541. #define MAGIC_1        0xAA
  542. #define MAX_LINE    80
  543.  
  544. char    buffer[SECSIZE];    /* The boot block buffer */
  545. int    bufmod=0;        /* buffer modified... */
  546.         /* (zero means buffer is unmodified) */
  547. int    useNTable;        /* boot sector uses name table */
  548.  
  549. /* device parameters (force someone to set them!) */
  550. unsigned cyls = DEFAULT_CYLS;
  551. unsigned heads = DEFAULT_HEADS;
  552. unsigned sectors = DEFAULT_SECTORS;
  553.  
  554. char    *devname;        /* device name */
  555. char    cmdline[MAX_LINE];
  556. char    filename[80];        /* used by r/w commands */
  557. char    *prompt;        /* null if no tty input */
  558.  
  559. /* Some of these strings are used in more than one place.
  560.  * For consistency, I put a newline on all of them.
  561.  */
  562. char h_h[] = "? <enter>             : Help summary\n";
  563. char h_l[] = "L                     : List partition table\n";
  564. char h_1[] = "1 id first last name  : set partition 1\n";
  565. char h_2[] = "2,3,4 ... (like 1)    : set respective partition\n";
  566. char h_a[] = "A n                   : Activate partition n\n";
  567. char h_g[] = "G cyls heads sectors  : set disk Geometry\n";
  568. char h_i[] = "I                     : list known ID numbers\n";
  569. char h_r[] = "R [optional-file]     : Read  device (or specified file)\n";
  570. char h_w[] = "W [optional-file]     : Write device (or specified file)\n";
  571. char h_q[] = "Q[!]                  : Quit (! means force)\n";
  572.  
  573. char * helpTable[] = {
  574. h_h, h_l, h_1, h_2, h_a, h_g, h_i, h_r, h_w, h_q,
  575. "# (All command letters have lower-case equivalents.)\n",
  576. (char *) 0 }; /* This MUST have a zero as the last element */
  577.  
  578. char *BadArg="Error: bad argument: %s\n";
  579. char *WarnNotSaved =
  580.     "Warning, modified partition table not saved.\n";
  581.  
  582. help()
  583. {
  584.   char ** p;
  585.   for (p = helpTable; *p; p++)
  586.     printf(*p);
  587. }
  588.  
  589. /* forward declarations */
  590. void    checkValidity();
  591. char *    setPartition();
  592. char *    makeActive();
  593. char *    setGeometry();
  594. ulong    chs2long();
  595. char *    nameID();
  596. int    printIDs();
  597.  
  598. main(argc,argv)
  599. int    argc;
  600. char    *argv[];
  601. {
  602.   char    *cmdp;        /* points to command word */
  603.   char    *argp;        /* points to command args */
  604.  
  605.   /* check command line args (device name) */
  606.   if (argc != 2) {
  607.     usage(argv[0]);    /* See s-sysname.c */
  608.     exit(1);
  609.   }
  610.   devname = argv[1];
  611.  
  612.   /* Should we prompt? */
  613.   prompt = (isatty(fileno(stdin))) ? PROMPT_STRING : (char *) 0;
  614.  
  615.   /* Print version name. */
  616.   fputs(versionString, stderr);
  617.  
  618.   /* get disk parameters */
  619.   getGeometry(devname,&cyls,&heads,§ors);
  620.  
  621.   /* Get the boot block. */
  622.   if (getBBlk(devname, buffer) < 0)
  623.     fprintf(stderr,"%s: read failed\n", devname);
  624.   checkValidity();
  625.  
  626.   if (prompt) fprintf(stderr,"For help, enter: '?'\n");
  627.  
  628.  
  629.   /* Read and process commands a line at a time. */
  630.   while (1) {
  631.     if (prompt) fputs(prompt,stdout);
  632.     if (! fgets(cmdline, MAX_LINE, stdin)) break;
  633.  
  634.     /* Find beginning of command word */
  635.     cmdp = cmdline;
  636.     while (isspace(*cmdp)) cmdp++;
  637.  
  638.     /* find beginning of args */
  639.     argp = cmdp;
  640.     while (*argp && !isspace(*argp)) argp++;
  641.     while (isspace(*argp) || *argp=='=') argp++;
  642.  
  643.     switch (*cmdp) {
  644.  
  645.     case '\0':        /* blank line */
  646.     case '#':        /* line comment */
  647.       break;
  648.  
  649.     case '?': case 'h': case 'H':
  650.       help();
  651.       break;
  652.  
  653.     case '1':    /* set partition entry */
  654.     case '2': case '3': case '4':
  655.       argp = setPartition(cmdp, argp);
  656.       if (argp) {    /* arg list error */
  657.     fprintf(stderr,BadArg,argp);
  658.     fprintf(stderr,h_1);
  659.     fprintf(stderr,h_2);
  660.     break;
  661.       }
  662.       bufmod = 1;
  663.       break;
  664.  
  665.     case 'a': case 'A':    /* activate partition */
  666.       argp = makeActive(argp);
  667.       if (argp) {
  668.     fprintf(stderr,BadArg,argp);
  669.     fprintf(stderr,h_a);
  670.     break;
  671.       }
  672.       bufmod = 1;
  673.       break;
  674.  
  675.     case 'g': case 'G':    /* set disk parameters (Geometry) */
  676.       argp = setGeometry(argp);
  677.       if (argp) {    /* arg list error */
  678.     fprintf(stderr,BadArg,argp);
  679.     fprintf(stderr,h_g);
  680.       }
  681.       break;
  682.  
  683.     case 'i': case 'I':    /* List known ID numbers */
  684.       printIDs();
  685.       break;
  686.  
  687.     case 'l': case 'L':    /* List the partition table */
  688.       listPTable();
  689.       break;
  690.  
  691.     case 'q': case 'Q':    /* Quit */
  692.       if (bufmod && (cmdp[1]  != '!')) {
  693.     fprintf(stderr,"\007%s%s\n", WarnNotSaved,
  694.         "Use 'wq' or 'q!' (enter ? for help).");
  695.     break;
  696.       }
  697.       exit(0);
  698.       /*NOTREACHED*/
  699.  
  700.     case 'r': case 'R':    /* read from device or file */
  701.       if (sscanf(argp,"%80s",filename) == 1) {
  702.     /* Arg specified, read from filename */
  703.     if (getFile(filename, buffer, SECSIZE) < 0)
  704.       fprintf(stderr,"%s: read failed\n", filename);
  705.     bufmod = 1;
  706.       } else {
  707.     /* No arg, use device. */
  708.     if (getBBlk(devname, buffer) < 0)
  709.       fprintf(stderr,"%s: read failed\n", devname);
  710.     bufmod = 0;
  711.       }
  712.       checkValidity();
  713.       break;
  714.  
  715.     case 'w': case 'W':    /* Write to file or device */
  716.       if (sscanf(argp,"%80s",filename) == 1) {
  717.     /* Arg specified, write to filename */
  718.     if (putFile(filename, buffer, SECSIZE) < 0)
  719.       fprintf(stderr, "%s: write failed\n", filename);
  720.       } else {  /* No arg, use device. */
  721.     if (putBBlk(devname, buffer) < 0)
  722.       fprintf(stderr, "%s: write failed\n", devname);
  723.     bufmod = 0;
  724.       }
  725.       if (cmdp[1] == 'q' || cmdp[1] == 'Q') exit(0);
  726.       break;
  727.  
  728.     default:
  729.       fprintf(stderr,"'%c': unrecognized.  Enter '?' for help.\n", *cmdp);
  730.       break;
  731.  
  732.     } /* switch */
  733.   } /* while */
  734.   if (bufmod) fprintf(stderr, WarnNotSaved);
  735.   exit(0);
  736. } /* main */
  737.  
  738.  
  739. /* Check for valid boot block (magic number in last two bytes).
  740.  * Also, check for presence of partition name table.
  741.  */
  742. void checkValidity()
  743. {
  744.   /* Check the magic number. */
  745.   if ((buffer[MAGIC_LOC] & 0xFF) != MAGIC_0 ||
  746.       (buffer[MAGIC_LOC+1] & 0xFF) != MAGIC_1 ) {
  747.     /* The boot sector is not valid -- Fix it. */
  748.     buffer[MAGIC_LOC] = MAGIC_0;
  749.     buffer[MAGIC_LOC+1] = MAGIC_1;
  750.     bufmod = 1;
  751.     fprintf(stderr,
  752. "\n\tWarning:  The boot sector has an invalid magic number.\n\
  753. \tThe magic number has been fixed, but the other contents\n\
  754. \tare probably garbage.  Initialize using the command:\n\
  755. \t\tR boot-program-file    (i.e. bootmenu.bin)\n\
  756. \tthen set each partition entry if necessary.\n");
  757.   }
  758.  
  759.   /* Does it use a name table (for a boot menu)?
  760.    * My boot program does, and can be identified by
  761.    * finding my name in a particular (unused) area.
  762.    */
  763.   useNTable = !strcmp(&buffer[LOC_GWR], "Gordon W. Ross");
  764.  
  765. }
  766.  
  767. char * setPartition(cmdp,argp)    /* return string on error */
  768. char    *cmdp,*argp;
  769. {
  770.   struct part *pp;    /* partition entry */
  771.   char *    np;        /* name table pointer */
  772.   char *    newname;    /* name field */
  773.   int    index;        /* partition index (0..3) */
  774.   uint    id;        /* ID code (see syscodes.c) */
  775.   uint    first,last;    /* user supplied cylinders */
  776.   uint    c,h,s;        /* working cyl,head,sect, */
  777.   uint    len;        /* chars seen by sscanf */
  778.   ulong    lsbeg, lslen;    /* logical begin, length */
  779.  
  780.   /* Value check the index */
  781.   index = *cmdp - '1';
  782.   if (index < 0 || index > 3)
  783.     return("index");
  784.   pp = (struct part *) &buffer[LOC_PT + index * 16];
  785.   np = &buffer[LOC_NT + index * 8];
  786.  
  787.   /* Read System ID */
  788.   if (sscanf(argp,"%i%n", &id, &len) < 1)
  789.     return("id");
  790.   argp += len;
  791.  
  792.   /* If ID==0, just clear out the entry and return. */
  793.   if (id == 0) {
  794.     strncpy( (char *) pp, "", 16);
  795.     if (useNTable) strncpy( np, "", 8);
  796.     return((char *)0);
  797.   }
  798.  
  799.   /* Read first and last cylinder */
  800.   if (sscanf(argp,"%i%i%n",&first, &last, &len) < 2)
  801.     return("first last (missing)");
  802.   argp += len;
  803.  
  804.   /* Reasonable start,end cylinder numbers? */
  805.   if (first > last)    return("first > last");
  806.   if (first > 1023)    return("first > 1023");
  807.   if (last >= cyls)    return("last >= cyls");
  808.  
  809.   /* Get (optional) system name. */
  810.   if (*argp == '\n') {    /* no name given, use default */
  811.     newname = nameID(id);
  812.   } else {        /* use the given name */
  813.     /* skip leading space */
  814.     while (*argp == ' ') argp++;
  815.     newname = argp;
  816.     /* Remove newline from end */
  817.     while (isgraph(*argp)||*argp==' ') argp++;
  818.     *argp = '\0';
  819.     useNTable = 1;
  820.   }
  821.  
  822.   /* Set the ID and name. */
  823.   pp->sysid = id;
  824.   if (useNTable) {
  825.     strncpy(np, newname, 8);
  826.     strcpy(&buffer[LOC_GWR], "Gordon W. Ross");
  827.   }
  828.  
  829.   /* set beginning c,h,s */
  830.   c = first;
  831.   /* if c == 0, head == 1 (reserve track 0) */
  832.   h = (first) ? 0 : 1;
  833.   s = 1;
  834.   pp->b_cyl = c & 0xFF;
  835.   pp->b_head = h;
  836.   pp->b_sec = s | ((c >> 2) & 0xC0);
  837.   /* Set the logical sector begin field */
  838.   lsbeg = lslen = chs2long(c,h,s); /* using lslen as temp. */
  839.   pp->lsBeg[0] = lslen & 0xff; lslen >>= 8;
  840.   pp->lsBeg[1] = lslen & 0xff; lslen >>= 8;
  841.   pp->lsBeg[2] = lslen & 0xff; lslen >>= 8;
  842.   pp->lsBeg[3] = lslen & 0xff; lslen >>= 8;
  843.  
  844.   /* set ending c,h,s (last may be larger than 1023) */
  845.   c = (last>1023) ? 1023 : last; /* limit c to 1023 */
  846.   h = heads - 1; s = sectors;
  847.   pp->e_cyl = c & 0xFF;
  848.   pp->e_head = h;
  849.   pp->e_sec = s | ((c >> 2) & 0xC0);
  850.   /* Set the logical sector length field (using REAL end cylinder) */
  851.   lslen = chs2long(last,h,s) + 1 - lsbeg;
  852.   pp->lsLen[0] = lslen & 0xff; lslen >>= 8;
  853.   pp->lsLen[1] = lslen & 0xff; lslen >>= 8;
  854.   pp->lsLen[2] = lslen & 0xff; lslen >>= 8;
  855.   pp->lsLen[3] = lslen & 0xff; lslen >>= 8;
  856.  
  857.   return((char *)0);    /* success */
  858. } /* setPartition() */
  859.  
  860. char * makeActive(argp)    /* return error string or zero */
  861. char    *argp;
  862. {
  863.   struct part *pp;    /* partition entry */
  864.   int    i,act;        /* which one becomes active */
  865.  
  866.   if (sscanf(argp,"%d", &act) < 1)
  867.     return("missing index");
  868.   act--;            /* make it zero-origin */
  869.  
  870.   i=0; pp = (struct part *) &buffer[LOC_PT];
  871.   while (i<4) {
  872.     pp->active = 0;
  873.     if (i == act) {
  874.       if (pp->sysid == 0) return("partition empty");
  875.       pp->active = 0x80;
  876.     }
  877.     i++; pp++;
  878.   }
  879.   return((char *)0);
  880. }
  881.  
  882. char * setGeometry(argp)    /* return string on error */
  883. char    *argp;
  884. {
  885.   int    c,h,s;
  886.  
  887.   if (sscanf(argp,"%i%i%i", &c, &h, &s) < 3)
  888.     return("(missing)");
  889.   if (c<1) return("cyls");
  890.   if (h<1) return("heads");
  891.   if (s<1) return("sectors");
  892.   cyls=c; heads=h; sectors=s;
  893.   return((char *)0);
  894. }
  895.  
  896. listPTable()        /* print out partition table */
  897. {
  898.   struct part * pp;    /* partition table entry */
  899.   char    *name;
  900.   int    i;        /* partition number */
  901.   int    numActive=0;    /* active partition [1-4], 0==none */
  902.   uint    pbc,pbh,pbs;    /* physical beginning  c,h,s */
  903.   uint    pec,peh,pes;    /* physical ending     c,h,s */
  904.   uint    lbc,lbh,lbs;    /* logical beginning   c,h,s */
  905.   uint    lec,leh,les;    /* logical ending      c,h,s */
  906.   ulong    lsbeg,lslen;    /* logical sectors: begin, length */
  907.  
  908.   printf("# Partition table on device: %s\n", devname);
  909.   printf("geometry %d %d %d (cyls heads sectors)\n",
  910.      cyls, heads, sectors);
  911.   printf("#  ID  First(cyl)  Last(cyl)  Name     ");
  912.   printf("# start, length (sectors)\n");
  913.  
  914.   for (i=0; i<4; i++) {
  915.     pp = (struct part *) &buffer[LOC_PT + i * 16];
  916.  
  917.     if (pp->active) {
  918.       if(numActive)
  919.     fprintf(stderr,"Error: multiple active partitions.\n");
  920.       else numActive = i+1;
  921.     }
  922.  
  923.     /* physical beginning c,h,s */
  924.     pbc = pp->b_cyl & 0xff | (pp->b_sec << 2) & 0x300;
  925.     pbh = pp->b_head;
  926.     pbs = pp->b_sec & 0x3F;
  927.  
  928.     /* physical ending c,h,s */
  929.     pec = pp->e_cyl & 0xff | (pp->e_sec << 2) & 0x300;
  930.     peh = pp->e_head;
  931.     pes = pp->e_sec & 0x3F;
  932.  
  933.     /* compute logical beginning (c,h,s) */
  934.     lsbeg = ((((((pp->lsBeg[3] ) << 8 )
  935.         | pp->lsBeg[2] ) << 8 )
  936.         | pp->lsBeg[1] ) << 8 )
  937.         | pp->lsBeg[0] ;
  938.     long2chs(lsbeg, &lbc, &lbh, &lbs);
  939.     /* compute logical ending (c,h,s) */
  940.     lslen = ((((((pp->lsLen[3]) << 8 )
  941.         | pp->lsLen[2]) << 8 )
  942.         | pp->lsLen[1]) << 8 )
  943.         | pp->lsLen[0] ;
  944.     /* keep beginning <= end ... */
  945.     if (lslen > 0) long2chs(lsbeg+lslen-1, &lec, &leh, &les);
  946.     else       long2chs(lsbeg,       &lec, &leh, &les);
  947.  
  948.     if (useNTable)
  949.       name = &buffer[LOC_NT + i * 8];
  950.     else
  951.       name = nameID((uint) pp->sysid);
  952.  
  953.     /* show physical begin, logical end (works for cyl>1023) */
  954.     /*      #  ID  First(cyl)  Last(cyl)  Name... # ... */
  955.     printf("%d %3d   %4d       %4d       %-8.8s # %ld, %ld\n",
  956.        i+1, pp->sysid, pbc, lec, name, lsbeg, lslen );
  957.  
  958.     /* That's all, for an empty partition. */
  959.     if (pp->sysid == 0) continue;
  960.  
  961.     /*
  962.      * Now do some consistency checks...
  963.      */
  964.  
  965.     /* Same physical / logical beginning? */
  966.     if (pbc != lbc || pbh != lbh || pbs != lbs ) {
  967.       printf("# note: first(%d): ", i+1);
  968.       printf("phys=(%d,%d,%d) ",    pbc, pbh, pbs);
  969.       printf("logical=(%d,%d,%d)\n",lbc, lbh, lbs);
  970.     }
  971.     /* Same physical / logical ending? */
  972.     if (pec != lec || peh != leh || pes != les ) {
  973.       printf("# note:  last(%d): ", i+1);
  974.       printf("phys=(%d,%d,%d) ",    pec, peh, pes);
  975.       printf("logical=(%d,%d,%d)\n",lec, leh, les);
  976.     }
  977.  
  978.     /* Beginning on cylinder boundary? */
  979.     if (pbc == 0) { /* exception: start on head 1 */
  980.       if (pbh != 1 || pbs != 1) {
  981.     printf("# note: first(%i): ", i+1);
  982.     printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  983.     printf("should be (%d,1,1)\n", pbc);
  984.       }
  985.     } else { /* not on cyl 0 */
  986.       if (pbh != 0 || pbs != 1) {
  987.     printf("# note: first(%i): ", i+1);
  988.     printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  989.     printf("should be (%d,0,1)\n", pbc);
  990.       }
  991.     }
  992.  
  993.     /* Ending on cylinder boundary? */
  994.     if (peh != (heads-1) || pes != sectors) {
  995.       printf("# note: last(%i): ", i+1);
  996.       printf("phys=(%d,%d,%d) ", pec, peh, pes);
  997.       printf("should be (%d,%d,%d)\n",
  998.          pec, heads-1, sectors);
  999.     }
  1000.  
  1001.   } /* for */
  1002.   printf("active: %d  %s\n", numActive,
  1003.      (numActive) ? "" : "(none)");
  1004. } /* listPTable() */
  1005.  
  1006. ulong chs2long(c,h,s)
  1007. uint c,h,s;
  1008. {
  1009.   ulong    l;
  1010.   if (s<1) s=1;
  1011.   l  = c; l *= heads;
  1012.   l += h; l *= sectors;
  1013.   l += (s - 1);
  1014.   return(l);
  1015. }
  1016.  
  1017. long2chs(ls, c, h, s)    /* convert logical sec-num to c,h,s */
  1018. ulong    ls;        /* Logical Sector number */
  1019. uint    *c,*h,*s;    /* cyl, head, sector */
  1020. {
  1021.   int    spc = heads * sectors;
  1022.   *c = ls / spc;
  1023.   ls = ls % spc;
  1024.   *h = ls / sectors;
  1025.   *s = ls % sectors + 1;    /* sectors count from 1 */
  1026. }
  1027.  
  1028. char * nameID(n)
  1029. unsigned int n;
  1030. {
  1031.   struct intString *is;
  1032.  
  1033.   is = sysCodes;
  1034.   while (is->i) {
  1035.     if (is->i == n) return(is->s);
  1036.     is++;
  1037.   }
  1038.   if (!n) return(is->s);
  1039.   return("unknown");
  1040. }
  1041.  
  1042. int printIDs()        /* print the known system IDs */
  1043. {
  1044.   struct intString * is = sysCodes;
  1045.  
  1046.   /* This might need to do more processing eventually, i.e.
  1047.    * if (prompt) { ... do more processing ... }
  1048.    */
  1049.   printf("_ID_\t__Name__ ____Description____\n");
  1050.   while (is->i) {
  1051.     printf("%3d\t%s\n", is->i, is->s);
  1052.     is++;
  1053.   }
  1054. }
  1055. SHAR_EOF
  1056. if test 15690 -ne "`wc -c < 'pfdisk.c'`"
  1057. then
  1058.     echo shar: error transmitting "'pfdisk.c'" '(should have been 15690 characters)'
  1059. fi
  1060. fi # end of overwriting check
  1061. echo shar: extracting "'syscodes.c'" '(1357 characters)'
  1062. if test -f 'syscodes.c'
  1063. then
  1064.     echo shar: will not over-write existing file "'syscodes.c'"
  1065. else
  1066. cat << \SHAR_EOF > 'syscodes.c'
  1067. /* This file holds all knowledge of partition ID codes.
  1068.  * Thanks to leendert@cs.vu.nl (Leendert van Doorn) for
  1069.  * collecting most of this information.
  1070.  */
  1071.  
  1072. #define extern
  1073. #include "syscodes.h"
  1074. #undef  extern
  1075.  
  1076. /* Note that my boot program menu can only use the first 8 characters
  1077.  * of these names.  The colon in the nineth position shows where the
  1078.  * first truncated char is.  (There's not much room in the bootblock!)
  1079.  */
  1080. struct intString sysCodes[] = {
  1081. { 0x01, "DOS-12  :12-bit FAT" },
  1082. { 0x02, "XENIX   :root" },
  1083. { 0x03, "XENIX   :usr" },
  1084. { 0x04, "DOS-16  :16-bit FAT" },
  1085. { 0x05, "DOS-ext :DOS 3.3 extended volume" },
  1086. { 0x06, "DOS-big :DOS 4.0 large volume" },
  1087. { 0x07, "OS/2    :OS/2 (or QNX or Adv. UNIX...)" },
  1088. { 0x08, "AIX     :file system" },
  1089. { 0x09, "AIX-boot:boot partition" },
  1090.  
  1091. { 0x10, "OPUS    :?" },
  1092. { 0x40, "VENIX   :Venix 80286" },
  1093. { 0x51, "NOVELL  :?" },
  1094. { 0x52, "CPM     :?" },
  1095. { 0x63, "UNIX    :System V/386" },
  1096. { 0x64, "NOVELL  :?" },
  1097. { 0x75, "PC/IX   :?" },
  1098. { 0x80, "Minix   :Minix (ver. 1.4a and earlier)" },
  1099. { 0x81, "Minix   :Minix (ver. 1.4b and later)" },
  1100. { 0x93, "Amoeba  :Amoeba file system" },
  1101. { 0x94, "Amoeba  :Amoeba bad block table?" },
  1102. { 0xDB,    "C.DOS   :Concurrent DOS" },
  1103.  
  1104. /* { 0xF2, "DOS-2nd :DOS 3.3+ second partition" }, */
  1105. /* { 0xFF, "BAD-TRK :Bad track table?" }, */
  1106.  
  1107. /* Make sure this is last! */
  1108. {    0, "(empty)" }
  1109. };
  1110. SHAR_EOF
  1111. if test 1357 -ne "`wc -c < 'syscodes.c'`"
  1112. then
  1113.     echo shar: error transmitting "'syscodes.c'" '(should have been 1357 characters)'
  1114. fi
  1115. fi # end of overwriting check
  1116. echo shar: extracting "'syscodes.h'" '(84 characters)'
  1117. if test -f 'syscodes.h'
  1118. then
  1119.     echo shar: will not over-write existing file "'syscodes.h'"
  1120. else
  1121. cat << \SHAR_EOF > 'syscodes.h'
  1122. struct intString { unsigned int i; char * s; };
  1123. extern struct intString sysCodes[];
  1124. SHAR_EOF
  1125. if test 84 -ne "`wc -c < 'syscodes.h'`"
  1126. then
  1127.     echo shar: error transmitting "'syscodes.h'" '(should have been 84 characters)'
  1128. fi
  1129. fi # end of overwriting check
  1130. echo shar: extracting "'sysdep.h'" '(675 characters)'
  1131. if test -f 'sysdep.h'
  1132. then
  1133.     echo shar: will not over-write existing file "'sysdep.h'"
  1134. else
  1135. cat << \SHAR_EOF > 'sysdep.h'
  1136. /* communicate declarations from the files: s_*.c */
  1137.  
  1138. #define SECSIZE 0x200
  1139.  
  1140. extern int usage();        /* print a usage message */
  1141.     /* (char *progname) */
  1142.  
  1143. extern void getGeometry(); /* determine disk parameters */
  1144.     /* (char *dev, uint *cyls, uint *heads, uint *sectors) */
  1145.  
  1146. extern int getFile();    /* open, read, close, return(num-read) */
  1147.     /* (char *name, char *buf, int len) */
  1148.  
  1149. extern int putFile();    /* open, write, close, return(num-writen) */
  1150.     /* (char *name, char *buf, int len) */
  1151.  
  1152. extern int getBBlk();    /* open, read, close, return(num-read) */
  1153.     /* (char *dev, char *buf) */
  1154.  
  1155. extern int putBBlk();    /* open, write, close, return(num-writen) */
  1156.     /* (char *dev, char *buf) */
  1157. SHAR_EOF
  1158. if test 675 -ne "`wc -c < 'sysdep.h'`"
  1159. then
  1160.     echo shar: error transmitting "'sysdep.h'" '(should have been 675 characters)'
  1161. fi
  1162. fi # end of overwriting check
  1163. echo shar: extracting "'s_esix.c'" '(3085 characters)'
  1164. if test -f 's_esix.c'
  1165. then
  1166.     echo shar: will not over-write existing file "'s_esix.c'"
  1167. else
  1168. cat << \SHAR_EOF > 's_esix.c'
  1169. /* This file contains system-specific functions for ESIX.
  1170.  * The program pfdisk.c calls these routines.
  1171.  * Note that ESIX can't use the generic Sys.V/386 version of
  1172.  * this file because it uses ioctl calls to access the
  1173.  * primary boot sector.  Other systems provide a device which
  1174.  * maps onto the whole disk (starting with the boot sector).
  1175.  */
  1176. #include <stdio.h>
  1177. #include <fcntl.h>
  1178. #include <sys/types.h>
  1179. #include <sys/vtoc.h>
  1180.  
  1181. #define extern
  1182. #include "sysdep.h"
  1183. #undef extern
  1184.  
  1185. int usage(prog)    /* print a usage message */
  1186. char    *prog;    /* program name */
  1187. {
  1188.   fprintf(stderr,"Usage: %s dev\n\t%s\n", prog,
  1189.       "where 'dev' is the device name, i.e. /dev/rdsk/0s0");
  1190. }
  1191.  
  1192. void getGeometry(dev, c, h, s)
  1193. char    *dev;        /* device name */
  1194. unsigned *c,*h,*s;    /* cyls, heads, sectors */
  1195. {
  1196.   int devfd, retval;
  1197.   struct disk_parms dp;
  1198.   
  1199.   devfd = open(dev, O_RDONLY, 0);
  1200.   if (devfd < 0) {
  1201.     fprintf(stderr,"%s: can't open for reading\n", dev);
  1202.     return;
  1203.   }
  1204.   retval = ioctl(devfd, V_GETPARMS, &dp);
  1205.   close(devfd);
  1206.   if (retval < 0) {
  1207.     fprintf(stderr,"%s: can't get disk parameters\n", dev);
  1208.     return;
  1209.   }
  1210.   if (dp.dp_type != DPT_WINI) {
  1211.     fprintf(stderr,"%s: not a Winchester Disk\n", dev);
  1212.     return;
  1213.   }
  1214.   *c = dp.dp_cyls;
  1215.   *h = dp.dp_heads;
  1216.   *s = dp.dp_sectors;
  1217. }
  1218.  
  1219. int getFile(name, buf, len)    /* read file into buffer */
  1220. char    *name, *buf;
  1221. int    len;
  1222. {    /* (open, read, close) */
  1223.   int devfd, retval;
  1224.   
  1225.   devfd = open(name, O_RDONLY, 0);
  1226.   if (devfd < 0) {
  1227.     fprintf(stderr,"%s: can't open for reading\n", name);
  1228.     return(devfd);
  1229.   }
  1230.   retval = read(devfd, buf, len);
  1231.   if (retval < 0)
  1232.     fprintf(stderr,"%s: read failed\n", name);
  1233.   close(devfd);
  1234.   return(retval);
  1235. }
  1236.  
  1237. int putFile(name, buf, len)    /* write buffer to file */
  1238. char    *name, *buf;
  1239. int    len;
  1240. {    /* (open, write, close) */
  1241.   int devfd, retval;
  1242.   
  1243.   devfd = open(name, O_WRONLY|O_CREAT, 0666);
  1244.   if (devfd < 0) {
  1245.     fprintf(stderr,"%s: can't open for writing\n", name);
  1246.     return(devfd);
  1247.   }
  1248.   retval = write(devfd, buf, len);
  1249.   if (retval < 0)
  1250.     fprintf(stderr,"%s: write failed\n", name);
  1251.   close(devfd);
  1252.   return(retval);
  1253. }
  1254.  
  1255. int getBBlk(name, buf)    /* read Boot Block into buffer */
  1256. char    *name, *buf;
  1257. {    /* (open, read, close) */
  1258.   int devfd, retval;
  1259.   struct absio abs;
  1260.   
  1261.   devfd = open(name, O_RDONLY, 0);
  1262.   if (devfd < 0) {
  1263.     fprintf(stderr,"%s: can't open for reading\n", name);
  1264.     return(devfd);
  1265.   }
  1266.   abs.abs_sec = 0;    /* the primary boot sector */
  1267.   abs.abs_buf = buf;
  1268.   retval = ioctl(devfd, V_RDABS, &abs);
  1269.   if (retval < 0)
  1270.     fprintf(stderr,"%s: read failed\n", name);
  1271.   close(devfd);
  1272.   return(retval);
  1273. }
  1274.  
  1275. int putBBlk(name, buf)    /* write buffer to Boot Block */
  1276. char    *name, *buf;
  1277. {    /* (open, write, close) */
  1278.   int devfd, retval;
  1279.   struct absio abs;
  1280.   
  1281.   devfd = open(name, O_WRONLY, 0);
  1282.   if (devfd < 0) {
  1283.     fprintf(stderr,"%s: can't open for writing\n", name);
  1284.     return(devfd);
  1285.   }
  1286.   abs.abs_sec = 0;    /* the primary boot sector */
  1287.   abs.abs_buf = buf;
  1288.   retval = ioctl(devfd, V_WRABS, &abs);
  1289.   if (retval < 0)
  1290.     fprintf(stderr,"%s: write failed\n", name);
  1291.   close(devfd);
  1292.   return(retval);
  1293. }
  1294. SHAR_EOF
  1295. if test 3085 -ne "`wc -c < 's_esix.c'`"
  1296. then
  1297.     echo shar: error transmitting "'s_esix.c'" '(should have been 3085 characters)'
  1298. fi
  1299. fi # end of overwriting check
  1300. echo shar: extracting "'s_i386.c'" '(2647 characters)'
  1301. if test -f 's_i386.c'
  1302. then
  1303.     echo shar: will not over-write existing file "'s_i386.c'"
  1304. else
  1305. cat << \SHAR_EOF > 's_i386.c'
  1306. /* This file contains system-specific functions suitable for
  1307.  * most AT&T System V/386 variants (ISC,SCO,Intel...).
  1308.  * The program pfdisk.c calls these routines.
  1309.  */
  1310. #include <stdio.h>
  1311. #include <fcntl.h>
  1312. #include <sys/types.h>
  1313. #include <sys/vtoc.h>
  1314.  
  1315. #define extern
  1316. #include "sysdep.h"
  1317. #undef extern
  1318.  
  1319. int usage(prog)    /* print a usage message */
  1320. char    *prog;    /* program name */
  1321. {
  1322.   fprintf(stderr,"Usage: %s dev\n\
  1323.     where 'dev' is the device name, i.e. /dev/rdsk/0p0\n\
  1324.     (The device must start on absolute sector zero.)\n",prog);
  1325. }
  1326.  
  1327. void getGeometry(dev, c, h, s)
  1328. char    *dev;        /* device name */
  1329. unsigned *c,*h,*s;    /* cyls, heads, sectors */
  1330. {
  1331.   int devfd, retval;
  1332.   struct disk_parms dp;
  1333.   
  1334.   devfd = open(dev, O_RDONLY, 0);
  1335.   if (devfd < 0) {
  1336.     fprintf(stderr,"%s: can't open for reading\n", dev);
  1337.     return;
  1338.   }
  1339.   retval = ioctl(devfd, V_GETPARMS, &dp);
  1340.   close(devfd);
  1341.   if (retval < 0) {
  1342.     fprintf(stderr,"%s: can't get disk parameters\n", dev);
  1343.     return;
  1344.   }
  1345.   if (dp.dp_type != DPT_WINI) {
  1346.     fprintf(stderr,"%s: not a Winchester Disk\n", dev);
  1347.     return;
  1348.   }
  1349.   *c = dp.dp_cyls;
  1350.   *h = dp.dp_heads;
  1351.   *s = dp.dp_sectors;
  1352. }
  1353.  
  1354. int getFile(name, buf, len)    /* read file into buffer */
  1355. char    *name, *buf;
  1356. int    len;
  1357. {    /* (open, read, close) */
  1358.   int devfd, retval;
  1359.   
  1360.   devfd = open(name, O_RDONLY, 0);
  1361.   if (devfd < 0) {
  1362.     fprintf(stderr,"%s: can't open for reading\n", name);
  1363.     return(devfd);
  1364.   }
  1365.   retval = read(devfd, buf, len);
  1366.   if (retval < 0)
  1367.     fprintf(stderr,"%s: read failed\n", name);
  1368.   close(devfd);
  1369.   return(retval);
  1370. }
  1371.  
  1372. int putFile(name, buf, len)    /* write buffer to file */
  1373. char    *name, *buf;
  1374. int    len;
  1375. {    /* (open, write, close) */
  1376.   int devfd, retval;
  1377.   
  1378.   devfd = open(name, O_WRONLY|O_CREAT, 0666);
  1379.   if (devfd < 0) {
  1380.     fprintf(stderr,"%s: can't open for writing\n", name);
  1381.     return(devfd);
  1382.   }
  1383.   retval = write(devfd, buf, len);
  1384.   if (retval < 0)
  1385.     fprintf(stderr,"%s: write failed\n", name);
  1386.   close(devfd);
  1387.   return(retval);
  1388. }
  1389.  
  1390. int getBBlk(devname, buffer)    /* read block into buffer */
  1391. char    *devname, *buffer;    /* (open, read, close) */
  1392. {
  1393.   int devfd, retval;
  1394.   
  1395.   devfd = open(devname,O_RDONLY);
  1396.   if (devfd < 0) {
  1397.     printf("%s: can't open for read\n", devname);
  1398.     return(devfd);
  1399.   }
  1400.   retval = read(devfd, buffer, SECSIZE);
  1401.   close(devfd);
  1402.   return(retval);
  1403. }
  1404.  
  1405. int putBBlk(devname, buffer)    /* write buffer to device */
  1406. char    *devname, *buffer;    /* (open, write, close) */
  1407. {
  1408.   int devfd, retval;
  1409.   
  1410.   devfd = open(devname,O_WRONLY);
  1411.   if (devfd < 0) {
  1412.     printf("%s: can't open for write\n",devname);
  1413.     return(devfd);
  1414.   }
  1415.   retval = write(devfd, buffer, SECSIZE);
  1416.   sync();
  1417.   close(devfd);
  1418.   return(retval);
  1419. }
  1420. SHAR_EOF
  1421. if test 2647 -ne "`wc -c < 's_i386.c'`"
  1422. then
  1423.     echo shar: error transmitting "'s_i386.c'" '(should have been 2647 characters)'
  1424. fi
  1425. fi # end of overwriting check
  1426. echo shar: extracting "'s_unix.c'" '(2426 characters)'
  1427. if test -f 's_unix.c'
  1428. then
  1429.     echo shar: will not over-write existing file "'s_unix.c'"
  1430. else
  1431. cat << \SHAR_EOF > 's_unix.c'
  1432. /* This file contains system-specific functions for generic UNIX.
  1433.  * The program pfdisk.c calls these routines.
  1434.  */
  1435. #include <stdio.h>
  1436. #include <fcntl.h>
  1437.  
  1438. #define extern
  1439. #include "sysdep.h"
  1440. #undef extern
  1441.  
  1442. int usage(prog)    /* print a usage message */
  1443. char    *prog;    /* program name */
  1444. {
  1445.   fprintf(stderr,"Usage: %s dev\n\
  1446. \twhere 'dev' is the device name, i.e. /dev/hd0\n\
  1447. \t(The device must start on absolute sector zero.)\n",prog);
  1448. }
  1449.  
  1450. void getGeometry(dev, c, h, s)
  1451. char    *dev;        /* device name */
  1452. unsigned *c,*h,*s;    /* cyls, heads, sectors */
  1453. {
  1454.   fprintf(stderr,
  1455. "\n\tWarning:  The device \"%s\" is assumed to have:\n\
  1456. \tcyls=%d, heads=%d, sectors=%d (an arbitrary guess).\n",
  1457.       dev, *c, *h, *s);
  1458.   fprintf(stderr,
  1459. "\n\tThis program was compiled for generic UNIX and therefore\n\
  1460. \tdoes not know how to determine the disk parameters.  You must\n\
  1461. \tdescribe the disk geometry manually, using the 'G' command.\n");
  1462. }
  1463.  
  1464. int getFile(name, buf, len)    /* read file into buffer */
  1465. char    *name, *buf;
  1466. int    len;
  1467. {    /* (open, read, close) */
  1468.   int devfd, retval;
  1469.   
  1470.   devfd = open(name, O_RDONLY, 0);
  1471.   if (devfd < 0) {
  1472.     fprintf(stderr,"%s: can't open for reading\n", name);
  1473.     return(devfd);
  1474.   }
  1475.   retval = read(devfd, buf, len);
  1476.   if (retval < 0)
  1477.     fprintf(stderr,"%s: read failed\n", name);
  1478.   close(devfd);
  1479.   return(retval);
  1480. }
  1481.  
  1482. int putFile(name, buf, len)    /* write buffer to file */
  1483. char    *name, *buf;
  1484. int    len;
  1485. {    /* (open, write, close) */
  1486.   int devfd, retval;
  1487.   
  1488.   devfd = open(name, O_WRONLY|O_CREAT, 0666);
  1489.   if (devfd < 0) {
  1490.     fprintf(stderr,"%s: can't open for writing\n", name);
  1491.     return(devfd);
  1492.   }
  1493.   retval = write(devfd, buf, len);
  1494.   if (retval < 0)
  1495.     fprintf(stderr,"%s: write failed\n", name);
  1496.   close(devfd);
  1497.   return(retval);
  1498. }
  1499.  
  1500. int getBBlk(devname, buffer)    /* read block into buffer */
  1501. char    *devname, *buffer;    /* (open, read, close) */
  1502. {
  1503.   int devfd, retval;
  1504.   
  1505.   devfd = open(devname,O_RDONLY);
  1506.   if (devfd < 0) {
  1507.     printf("%s: can't open for read\n", devname);
  1508.     return(devfd);
  1509.   }
  1510.   retval = read(devfd, buffer, SECSIZE);
  1511.   close(devfd);
  1512.   return(retval);
  1513. }
  1514.  
  1515. int putBBlk(devname, buffer)    /* write buffer to device */
  1516. char    *devname, *buffer;    /* (open, write, close) */
  1517. {
  1518.   int devfd, retval;
  1519.   
  1520.   devfd = open(devname,O_WRONLY);
  1521.   if (devfd < 0) {
  1522.     printf("%s: can't open for write\n",devname);
  1523.     return(devfd);
  1524.   }
  1525.   retval = write(devfd, buffer, SECSIZE);
  1526.   sync();
  1527.   close(devfd);
  1528.   return(retval);
  1529. }
  1530. SHAR_EOF
  1531. if test 2426 -ne "`wc -c < 's_unix.c'`"
  1532. then
  1533.     echo shar: error transmitting "'s_unix.c'" '(should have been 2426 characters)'
  1534. fi
  1535. fi # end of overwriting check
  1536. echo shar: extracting "'s_msdos.c'" '(3768 characters)'
  1537. if test -f 's_msdos.c'
  1538. then
  1539.     echo shar: will not over-write existing file "'s_msdos.c'"
  1540. else
  1541. cat << \SHAR_EOF > 's_msdos.c'
  1542. /* This file contains system-specific functions for MS-DOS.
  1543.  * The program pfdisk.c calls these routines.
  1544.  */
  1545. #include <stdio.h>
  1546. #include <fcntl.h>
  1547. #include <sys/types.h>
  1548. #include <sys/stat.h>
  1549. #include <dos.h>
  1550.  
  1551. #define extern
  1552. #include "sysdep.h"
  1553. #undef extern
  1554.  
  1555. int usage(prog)    /* print a usage message */
  1556. char    *prog;    /* program name */
  1557. {
  1558.   fprintf(stderr,"Usage: %s <disk>\n", prog);
  1559.   fprintf(stderr,"\twhere <disk> is a digit [0-9]\n");
  1560. }
  1561.  
  1562. void getGeometry(name, c, h, s)
  1563. char    *name;        /* device name */
  1564. unsigned *c,*h,*s;    /* cyls, heads, sectors */
  1565. {
  1566.   int dev;    /* hard disk number */
  1567.   union     REGS    regs;
  1568.   struct    SREGS    sregs;
  1569.   
  1570.   if (name[0] < '0' ||
  1571.       name[0] > '9' ||
  1572.       name[1] != 0  )
  1573.     {
  1574.       fprintf(stderr,"%s: device name must be a digit\n", name);
  1575.       return;
  1576.     }
  1577.   dev = (name[0] - '0');
  1578.   
  1579.   regs.h.ah = 8;        /* get param.    */
  1580.   regs.h.dl = dev | 0x80;
  1581.   
  1582.   int86x(0x13,®s,®s,&sregs);
  1583.   
  1584.   /* Are that many drives responding? */
  1585.   if (regs.h.dl <= dev ) {
  1586.     fprintf(stderr,"%s: drive not found\n", name);
  1587.     return;
  1588.   }
  1589.   if (regs.x.cflag) {
  1590.     fprintf(stderr,"%s: can't get disk parameters\n", name);
  1591.     return;
  1592.   }
  1593.   *c = ((((int) regs.h.cl << 2) & 0x300) | regs.h.ch) + 1;
  1594.   *h = regs.h.dh + 1;
  1595.   *s = regs.h.cl & 0x3F;
  1596. }
  1597.  
  1598. int getFile(name, buf, len)    /* read file into buffer */
  1599. char    *name, *buf;
  1600. int    len;
  1601. {    /* (open, read, close) */
  1602.   int devfd, retval;
  1603.   
  1604.   devfd = open(name, O_RDONLY|O_BINARY, 0);
  1605.   if (devfd < 0) {
  1606.     fprintf(stderr,"%s: can't open for reading\n", name);
  1607.     return(devfd);
  1608.   }
  1609.   retval = read(devfd, buf, len);
  1610.   if (retval < 0)
  1611.     fprintf(stderr,"%s: read failed\n", name);
  1612.   close(devfd);
  1613.   return(retval);
  1614. }
  1615.  
  1616. int putFile(name, buf, len)    /* write buffer to file */
  1617. char    *name, *buf;
  1618. int    len;
  1619. {    /* (open, write, close) */
  1620.   int devfd, retval;
  1621.   
  1622.   devfd = open(name,
  1623.            O_WRONLY|O_CREAT|O_BINARY,
  1624.            S_IREAD|S_IWRITE ); /* stupid DOS... */
  1625.   if (devfd < 0) {
  1626.     fprintf(stderr,"%s: can't open for writing\n", name);
  1627.     return(devfd);
  1628.   }
  1629.   retval = write(devfd, buf, len);
  1630.   if (retval < 0)
  1631.     fprintf(stderr,"%s: write failed\n", name);
  1632.   close(devfd);
  1633.   return(retval);
  1634. }
  1635.  
  1636. int getBBlk(name, buf)    /* read boot block into buffer */
  1637. char    *name, *buf;
  1638. {    /* BIOS absolute disk read */
  1639.   int dev;
  1640.   union     REGS    regs;
  1641.   struct    SREGS    sregs;
  1642.   
  1643.   if (name[0] < '0' ||
  1644.       name[0] > '9' ||
  1645.       name[1] != 0  )
  1646.     {
  1647.       fprintf(stderr,"%s: device name must be a digit\n",name);
  1648.       return(-1);
  1649.     }
  1650.   dev = (name[0] - '0');
  1651.   
  1652.   segread(&sregs);    /* get ds */
  1653.   sregs.es = sregs.ds;    /* buffer address */
  1654.   regs.x.bx = (int) buf;
  1655.   
  1656.   regs.h.ah = 2;        /* read        */
  1657.   regs.h.al = 1;        /* sector count    */
  1658.   regs.h.ch = 0;        /* track    */
  1659.   regs.h.cl = 1;        /* start sector    */
  1660.   regs.h.dh = 0;        /* head        */
  1661.   regs.h.dl = dev|0x80;    /* drive    */
  1662.   
  1663.   int86x(0x13,®s,®s,&sregs);
  1664.   if (regs.x.cflag) {
  1665.     fprintf(stderr,"%s: read failed\n", name);
  1666.     return(-1);
  1667.   }
  1668.   return(SECSIZE);
  1669. }
  1670.  
  1671. int putBBlk(name, buf)    /* write buffer to boot block */
  1672. char    *name, *buf;
  1673. {    /* BIOS absolute disk write */
  1674.   int dev;
  1675.   union     REGS    regs;
  1676.   struct    SREGS    sregs;
  1677.   
  1678.   if (name[0] < '0' ||
  1679.       name[0] > '9' ||
  1680.       name[1] != 0  )
  1681.     {
  1682.       fprintf(stderr,"%s: device name must be a digit\n", name);
  1683.       return(-1);
  1684.     }
  1685.   dev = (name[0] - '0');
  1686.   
  1687.   segread(&sregs);    /* get ds */
  1688.   sregs.es = sregs.ds;    /* buffer address */
  1689.   regs.x.bx = (int) buf;
  1690.   
  1691.   regs.h.ah = 3;        /* write    */
  1692.   regs.h.al = 1;        /* sector count    */
  1693.   regs.h.ch = 0;        /* track    */
  1694.   regs.h.cl = 1;        /* start sector    */
  1695.   regs.h.dh = 0;        /* head        */
  1696.   regs.h.dl = dev|0x80;    /* drive    */
  1697.   
  1698.   int86x(0x13,®s,®s,&sregs);
  1699.   if (regs.x.cflag) {
  1700.     fprintf(stderr,"%s: write failed\n",name);
  1701.     return(-1);
  1702.   }
  1703.   return(SECSIZE);
  1704. }
  1705. SHAR_EOF
  1706. if test 3768 -ne "`wc -c < 's_msdos.c'`"
  1707. then
  1708.     echo shar: error transmitting "'s_msdos.c'" '(should have been 3768 characters)'
  1709. fi
  1710. fi # end of overwriting check
  1711. #    End of shell archive
  1712. exit 0
  1713.  
  1714.